import { Injector } from '@angular/core';
import { DesignViewModelService } from '@farris/designer-services';
import { FarrisContextMenuService } from '@farris/ui-context-menu';
import { MessagerService } from '@farris/ui-messager';
import { Subject } from 'rxjs';
import { TableTdWidgetHelper } from './td-helper';

/**
 * 单元格菜单管理类
 */
export class TableTdManager {

    /** 重绘表格 */
    redrawTable = new Subject();

    /** 右键菜单服务类 */
    private contextMenuService: FarrisContextMenuService;

    /** 选中的单元格所在的列 */
    targetColumn: any;
    /** 选中单元格所在的行 */
    targetRow: any;
    /** 选中单元格列索引 */
    selectedColumnIndex: number;
    /** 选中单元格行索引 */
    selectedRowIndex: number;
    /** 选中单元格DOM节点 */
    targetTdElement: HTMLElement;
    /** 选中单元格id */
    targetTdId: string;

    /** 右键菜单配置 */
    menuConfig: any[] = [];
    /** 单元格菜单的服务类 */
    tableTdHelper: TableTdWidgetHelper;

    viewModelId: string;

    /** 简单表格下设计时合并的单元格：标签类单元格和编辑器类单元格为一组 */
    targetMergedTdIds: string[] = [];

    constructor(public component: any, public injector: Injector) {
        this.contextMenuService = this.injector.get(FarrisContextMenuService);
        this.tableTdHelper = new TableTdWidgetHelper();
    }
    /**
     * 获取菜单配置
     */
    getMenuConfig() {
        this.menuConfig = [] as any[];
        this.menuConfig.push(
            {
                id: 'insertColumnToLeft',
                title: '左插入列',
                handle: () => this.insertColumnToLeft(),
            },
            {
                id: 'insertColumnToRight',
                title: '右插入列',
                handle: () => this.insertColumnToRight()
            },
            {
                id: 'insertRowToTop',
                title: '上插入行',
                handle: () => this.insertRowToTop()
            },
            {
                id: 'insertRowToBottom',
                title: '下插入行',
                handle: () => this.insertRowToBottom()
            },
            '-',
            {
                id: 'mergeColumnToRight',
                title: '向右合并',
                divider: true,
                handle: () => this.mergeColumnToRight(),
                disable: !this.showMergeColumnToRight()
            },
            {
                id: 'mergeRowToBottom',
                title: '向下合并',
                handle: () => this.mergeRowToBottom(),
                disable: !this.showMergeRowToBottom()
            },
            '-',
            {
                id: 'splitColumns',
                title: '拆分成列',
                divider: true,
                handle: () => this.splitColumns(),
                disable: !this.showSplitColumns()

            },
            {
                id: 'splitRows',
                title: '拆分成行',
                handle: () => this.splitRows(),
                disable: !this.showSplitRows()
            },
            '-',
            {
                id: 'removeColumn',
                title: '删除当前列',
                divider: true,
                handle: () => this.removeColumn(),
                disable: !this.showRemoveColumn()
            },
            {
                id: 'removeRow',
                title: '删除当前行',
                handle: () => this.removeRow(),
                disable: !this.showRemoveRow()
            }
        );
    }

    showContextMenu($event, widgetPanelElement: HTMLElement) {
        this.getMenuConfig();
        if (!this.menuConfig || this.menuConfig.length === 0) {
            this.contextMenuService.hide();
            return;
        }
        $event.preventDefault();

        // 动态创建自定义右键菜单
        this.contextMenuService.show({
            id: this.component.id,
            activeDom: widgetPanelElement,
            menuItems: this.menuConfig,
            event: $event,
            highlight: false
        });

        $event.stopPropagation();
    }
    /**
     * 向左插入列
     */
    insertColumnToLeft() {
        this.tableTdHelper.insertColumns(this.component.rows, this.selectedColumnIndex);
        this.selectedColumnIndex++;
        this.redrawTable.next();
    }

    /**
     * 向右插入列
     */
    insertColumnToRight() {
        const targetColumnIndex = this.targetColumn.colspan > 1 ?
            this.tableTdHelper.findNextColIndex(this.selectedRowIndex, this.selectedColumnIndex + 1, this.component.rows) :
            this.selectedColumnIndex + 1;

        this.tableTdHelper.insertColumns(this.component.rows, targetColumnIndex);

        this.redrawTable.next();
    }
    /**
     * 向上插入行
     */
    insertRowToTop() {
        this.tableTdHelper.insertRow(this.selectedRowIndex, this.component.rows);
        this.selectedRowIndex++;

        this.redrawTable.next();
    }
    /**
     * 向下插入行
     */
    insertRowToBottom() {
        const targetRowIndex = this.targetColumn.rowspan > 1 ?
            this.tableTdHelper.findNextRowIndex(this.selectedRowIndex + 1, this.selectedColumnIndex, this.component.rows) :
            this.selectedRowIndex + 1;
        this.tableTdHelper.insertRow(targetRowIndex, this.component.rows);

        this.redrawTable.next();
    }

    /**
     * 向右合并是否可用
     * @returns boolean
     */
    showMergeColumnToRight(): boolean {
        const rowspan = this.targetColumn.rowspan;
        const colspan = this.targetColumn.colspan;
        if (this.selectedColumnIndex + colspan < this.targetRow.columns.length) {
            const n = this.targetRow.columns[colspan + this.selectedColumnIndex];
            if (!n.invisible && rowspan === n.rowspan) {
                return true;
            }
        }
        return false;
    }

    /**
     * 向右合并列
     */
    mergeColumnToRight() {
        const targetColspan = this.targetColumn.colspan;
        const o = this.selectedColumnIndex + targetColspan;
        const rightColumn = this.component.rows[this.selectedRowIndex].columns[o];
        if (rightColumn.editor && rightColumn.editor.type) {
            const msgService = this.injector.get(MessagerService);
            msgService.question('合并后将重置右侧单元格的编辑器，确定合并？', () => {

                // 同步ViewModel
                this.removeDesignViewModelFieldInColumns([rightColumn]);

                this.confirmToMergeColumnToRight(rightColumn, targetColspan);
            });
        } else {
            this.confirmToMergeColumnToRight(rightColumn, targetColspan);
        }

    }
    /**
     * 确认向右合并列
     * @param rightColumn 右侧列
     * @param targetColspan 当前单元格列数
     */
    confirmToMergeColumnToRight(rightColumn: any, targetColspan: number) {
        const r = rightColumn.colspan;
        this.targetColumn.colspan = targetColspan + r;
        rightColumn.invisible = true;

        // 被合并的单元格中editor废弃。
        this.resetTd(rightColumn);

        this.tableTdHelper.markTableItem(this.selectedRowIndex, this.selectedColumnIndex, this.component.rows);

        this.redrawTable.next();
    }

    /**
     * 向下合并是否可用
     * @returns boolean
     */
    private showMergeRowToBottom(): boolean {
        const t = this.component.rows[this.selectedRowIndex].columns[this.selectedColumnIndex].rowspan;
        const e = this.component.rows[this.selectedRowIndex].columns[this.selectedColumnIndex].colspan;
        if (t + this.selectedRowIndex < this.component.rows.length) {
            const n = this.component.rows[t + this.selectedRowIndex].columns[this.selectedColumnIndex];
            if (!n.invisible && e === n.colspan) {
                return true;

            }
        }
        return false;
    }
    /**
     * 向下合并行
     */
    private mergeRowToBottom() {

        const targetRowspan = this.targetColumn.rowspan;
        const o = this.selectedRowIndex + targetRowspan;

        const bottomColumn = this.component.rows[o].columns[this.selectedColumnIndex];
        if (bottomColumn.editor && bottomColumn.editor.type) {
            const msgService = this.injector.get(MessagerService);
            msgService.question('合并后将重置下方单元格的编辑器，确定合并？', () => {

                // 同步ViewModel
                this.removeDesignViewModelFieldInColumns([bottomColumn]);

                this.confirmToMergeRowToBottom(bottomColumn, targetRowspan);
            });
        } else {
            this.confirmToMergeRowToBottom(bottomColumn, targetRowspan);

        }

    }

    /**
     * 确定向下合并
     * @param bottomColumn 下方单元格
     * @param targetRowspan 当前单元格占用行数
     */
    private confirmToMergeRowToBottom(bottomColumn: any, targetRowspan: number) {
        this.targetColumn.rowspan = targetRowspan + bottomColumn.rowspan;
        bottomColumn.invisible = true;

        this.resetTd(bottomColumn);

        this.tableTdHelper.markTableItem(this.selectedRowIndex, this.selectedColumnIndex, this.component.rows);

        this.redrawTable.next();
    }
    /**
     * 重置单元格，默认静态文本，清除已有的编辑器
     * @param column 单元格
     */
    private resetTd(column: any) {
        column.staticText = {
            text: '',
            require: false
        };

        column.editor = {
            type: null,
            binding: null
        };
    }
    /**
     * 移除单元格中绑定的字段，适用于单元格被合并或者移除
     * @param columns 单元格列表
     */
    removeDesignViewModelFieldInColumns(columns: any[]) {
        const dgVMService = this.injector.get(DesignViewModelService);
        const dgViewModel = dgVMService.getDgViewModel(this.viewModelId);
        const fieldIds = [];
        columns.forEach(co => {
            if (co.editor && co.editor.binding && co.editor.binding.field) {
                const fieldId = co.editor.binding.field;
                fieldIds.push(fieldId);
            }
        });
        dgViewModel.removeField(fieldIds);
    }
    /**
     * 拆分成列是否可用
     */
    showSplitColumns(): boolean {
        return this.component.rows[this.selectedRowIndex].columns[this.selectedColumnIndex].colspan > 1;

    }
    /**
     * 拆分成列
     */
    splitColumns() {
        const colspan = this.component.rows[this.selectedRowIndex].columns[this.selectedColumnIndex].colspan;
        const rowspan = this.component.rows[this.selectedRowIndex].columns[this.selectedColumnIndex].rowspan;
        for (let i = 0; i < colspan; i++) {
            this.component.rows[this.selectedRowIndex].columns[this.selectedColumnIndex + i].invisible = false;
            this.component.rows[this.selectedRowIndex].columns[this.selectedColumnIndex + i].colspan = 1;
            this.component.rows[this.selectedRowIndex].columns[this.selectedColumnIndex + i].rowspan = rowspan;
            this.tableTdHelper.markTableItem(this.selectedRowIndex, this.selectedColumnIndex + i, this.component.rows);
        }

        this.redrawTable.next();
    }
    /**
     * 拆分成行是否可用
     */
    private showSplitRows(): boolean {
        return this.component.rows[this.selectedRowIndex].columns[this.selectedColumnIndex].rowspan > 1;

    }
    /**
     * 拆分成行
     */
    private splitRows() {

        const colspan = this.component.rows[this.selectedRowIndex].columns[this.selectedColumnIndex].colspan;
        const rowspan = this.component.rows[this.selectedRowIndex].columns[this.selectedColumnIndex].rowspan;
        for (let i = 0; i < rowspan; i++) {
            this.component.rows[this.selectedRowIndex + i].columns[this.selectedColumnIndex].invisible = false;
            this.component.rows[this.selectedRowIndex + i].columns[this.selectedColumnIndex].rowspan = 1;
            this.component.rows[this.selectedRowIndex + i].columns[this.selectedColumnIndex].colspan = colspan;
            this.tableTdHelper.markTableItem(this.selectedRowIndex, this.selectedColumnIndex + i, this.component.rows);
        }

        this.redrawTable.next();
    }
    /**
     * 是否支持删除列：合并后的列不支持移除
     * @returns boolean
     */
    showRemoveColumn(): boolean {
        const rows = this.component.rows;
        if (rows[this.selectedRowIndex].columns.length > 1) {
            const t = rows[this.selectedRowIndex].columns[this.selectedColumnIndex].colspan;
            if (1 === t) {
                return true;
            }

        }
        return false;
    }
    /**
     * 移除当前列
     */
    removeColumn() {

        const hasEditor = this.checkIfHasEditorInColumn();
        if (hasEditor) {
            const msgService = this.injector.get(MessagerService);
            msgService.question('确定移除当前列所有的编辑器配置？', () => {
                this.confirmRemoveColumn();
            });
        } else {
            this.confirmRemoveColumn();
        }
    }
    /**
     * 确定移除当前列
     */
    confirmRemoveColumn() {
        const rows = this.component.rows;
        const deletedColumns = [];
        for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {
            const colspan = rows[rowIndex].columns[this.selectedColumnIndex].colspan;
            const rowspan = rows[rowIndex].columns[this.selectedColumnIndex].rowspan;
            if (rows[rowIndex].columns[this.selectedColumnIndex].invisible) {
                const r = this.tableTdHelper.findPrevColIndex(rowIndex, this.selectedColumnIndex, rows);
                if (r !== this.selectedColumnIndex && rows[rowIndex].columns[r].colspan > 1) {
                    rows[rowIndex].columns[r].colspan = rows[rowIndex].columns[r].colspan - 1;
                }
            } else {
                if (colspan > 1) {
                    rows[rowIndex].columns[this.selectedColumnIndex + 1].invisible = false;
                    rows[rowIndex].columns[this.selectedColumnIndex + 1].colspan = colspan - 1;
                    rows[rowIndex].columns[this.selectedColumnIndex + 1].rowspan = rowspan;
                    this.tableTdHelper.markTableItem(rowIndex, this.selectedColumnIndex + 1, rows);
                }
            }
            deletedColumns.push(rows[rowIndex].columns[this.selectedColumnIndex]);

            rows[rowIndex].columns.splice(this.selectedColumnIndex, 1);

        }

        this.removeDesignViewModelFieldInColumns(deletedColumns);

        this.redrawTable.next({
            clearPropertyPanel: true
        });
    }
    /**
     * 校验同列的单元格中是否包含编辑器配置
     */
    checkIfHasEditorInColumn() {
        const rows = this.component.rows;
        for (const row of rows) {
            const column = row.columns[this.selectedColumnIndex];
            if (column && column.tdType === 'editor' && column.editor && column.editor.binding) {
                return true;
            }
        }

        return false;
    }
    /**
     * 是否支持移除行：合并后的行不支持移除
     * @returns boolean
     */
    showRemoveRow(): boolean {
        const rows = this.component.rows;
        if (rows.length > 1) {
            const t = rows[this.selectedRowIndex].columns[this.selectedColumnIndex].rowspan;
            if (1 === t) {
                return true;
            }

        }
        return false;
    }
    /**
     * 移除当前行
     */
    removeRow() {

        const hasEditor = this.checkIfHasEditorInRow();
        if (hasEditor) {
            const msgService = this.injector.get(MessagerService);
            msgService.question('确定移除当前行所有的编辑器配置？', () => {
                this.confirmRemoveRow();
            });
        } else {
            this.confirmRemoveRow();
        }

    }
    /**
     * 校验同列的单元格中是否包含编辑器配置
     */
    checkIfHasEditorInRow() {
        const rows = this.component.rows;
        for (const column of rows[this.selectedRowIndex].columns) {
            if (column && column.tdType === 'editor' && column.editor && column.editor.binding) {
                return true;
            }
        }

        return false;
    }
    /**
     * 确认移除当前行
     */
    confirmRemoveRow() {
        const rows = this.component.rows;

        for (let e = 0; e < rows[this.selectedRowIndex].columns.length; e++) {
            const n = rows[this.selectedRowIndex].columns[e].rowspan;
            const o = rows[this.selectedRowIndex].columns[e].colspan;
            if (rows[this.selectedRowIndex].columns[e].invisible) {
                const r = this.tableTdHelper.findPrevRowIndex(this.selectedRowIndex, e, rows);
                if (r !== this.selectedRowIndex && rows[r].columns[e].rowspan > 1) {
                    rows[r].columns[e].rowspan = rows[r].columns[e].rowspan - 1;
                }

            } else {
                if (n > 1) {
                    // 暂不支持合并行后的单元格删除行
                    rows[this.selectedRowIndex + 1].columns[e].invisible = false,
                        rows[this.selectedRowIndex + 1].columns[e].rowspan = n - 1;
                    rows[this.selectedRowIndex + 1].columns[e].colspan = o;
                    this.tableTdHelper.markTableItem(this.selectedRowIndex + 1, e, rows)
                }

            }

        }
        this.removeDesignViewModelFieldInColumns(rows[this.selectedRowIndex].columns);

        rows.splice(this.selectedRowIndex, 1);

        this.redrawTable.next({
            clearPropertyPanel: true
        });
    }


}
